package feng.process.api.service;

import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;

import feng.process.ProcessDataInfo;
import feng.process.ProcessObject;
import feng.process.api.bean.ParamTaskDealBean;
import feng.process.api.user.UserSelecter;
import feng.process.base.bean.StepBean;
import feng.process.base.step.TaskStep;
import feng.process.cont.ProcessConst;
import feng.process.dao.QueryDao;
import feng.process.dao.UpdateDao;
import feng.process.dao.bean.ParamProcessInstanceBean;
import feng.process.dao.bean.ParamProcessTaskBean;
import feng.process.dao.bean.ParamTaskUserRefBean;
import feng.process.util.StringUtil;

/**
 * 环节处理操作Service
 * @author 冯昌硕
 * @create 2012-10-29 下午11:40:16
 */
public class TaskDealService {

    private static final Logger log = Logger.getLogger(TaskDealService.class);
    
    private UpdateDao updateDao;
    
    private QueryDao queryDao;
    
    /**
     * 待办人员查询器
     */
    private UserSelecter userSelecter;
    
    public TaskDealService() throws Exception {
        updateDao = new UpdateDao();
        userSelecter = new UserSelecter();
        queryDao = new QueryDao();
    }
    
    /**
     * 功能：完成当前环节，进入下一环节
     * 
     * @param ptaskDealBean
     * @return
     * @create 2012-10-29 下午11:41:59
     */
    public boolean finishCurrTask(ParamTaskDealBean ptaskDealBean) {
        try {
            // 判断当前传入的处理人是否能够处理该工单
            ParamTaskUserRefBean paramUserRefBean = new ParamTaskUserRefBean();
            paramUserRefBean.setTkid(ptaskDealBean.getTaskId());
            paramUserRefBean.setWaitUserId(ptaskDealBean.getDealUserId());
            Object taskUserObj = queryDao.queryForObject("process_task_user_ref.selTaskWaitUserByTkid", paramUserRefBean);
            if(null == taskUserObj) {
                throw new Exception("工单["+ptaskDealBean.getFlowId()+"]环节["+ptaskDealBean.getStepId()+"]人员["+ptaskDealBean.getDealUserId()+"]无权处理");
            }
            
            updateDao.startTransaction();
            
            // 1. 更新process_task环节处理记录
            ParamProcessTaskBean paramTaskBean = new ParamProcessTaskBean();
            paramTaskBean.setTkid(ptaskDealBean.getTaskId());
            paramTaskBean.setDealUserId(ptaskDealBean.getDealUserId());
            paramTaskBean.setStatus(ProcessConst.PROCESS_TASK_STATUS_DEALED);
            paramTaskBean.setFlowId(ptaskDealBean.getFlowId());
            paramTaskBean.setStepId(ptaskDealBean.getStepId());
            
            
            // 查询当前要处理的环节是否已经被处理过
            Object taskStatusObj = queryDao.queryForObject("process_task.selTaskStatus", paramTaskBean);
            if(null != taskStatusObj) {
                Integer status = (Integer) taskStatusObj;
                if(status == ProcessConst.PROCESS_TASK_STATUS_DEALED) {
                    throw new Exception("工单["+ptaskDealBean.getFlowId()+"]环节["+ptaskDealBean.getStepId()+"]已经被处理过");
                }
            } else {
                throw new Exception("工单["+ptaskDealBean.getFlowId()+"]环节["+ptaskDealBean.getStepId()+"]未查询到状态，请检查数据库");
            }
            
            int updTaskCnt = updateDao.update("process_task.updProcessTaskFinish", paramTaskBean);
            log.debug("更新process_task:tkid=["+ptaskDealBean.getTaskId()+"] 影响行数=["+ updTaskCnt +"]");
            if(updTaskCnt <= 0) {
                log.info("更新process_task:tkid=["+ptaskDealBean.getTaskId()+"] 影响记录数小于一条，没有造成更新");
                throw new Exception("process_task.updProcessTaskFinish 更新结果返回值小于1");
            }
            
            // 2. 取当前环节
            String currStepId = ptaskDealBean.getStepId();
            ProcessObject processObj = ProcessDataInfo.processMap.get(ptaskDealBean.getTempleteName());
            
            // 这里实现环节的处理，通过executeTask调用获取下一环节要跳转到哪里去
            TaskStep taskStep = processObj.getTaskStepMap().get(currStepId);
            String nextStepId = taskStep.executeTask();
            log.debug("当前操作的TaskStep.executeTask获取的下一环节=["+nextStepId+"]");
            
            // 查找当前环节对应的StepBean对象
            List<StepBean> stepBeanLst = processObj.getStepBeanLst();
            StepBean currStepBean = findStepBean(stepBeanLst, currStepId);
            
            log.debug("当前操作的StepBean属性：currStepBean=["+currStepBean+"]");
            if(null == currStepBean) {
                throw new Exception("未找到环节["+currStepId+"]对应的StepBean");
            }
            
            List<String> nextStepIds = currStepBean.getNextStepIds();
            if(!nextStepIds.contains(nextStepId)) {
                throw new Exception("TaskStep.executeTask获取的下一环节["+nextStepId+"]不在集合["+nextStepIds+"]中，请检查流程模板配置文件环节ID配置");
            }
            
            // TaskStep.executeTask调用返回值是否为结束环节的标识
            if(ProcessConst.PROCESS_TASK_STEP_ID_FINISH.equals(nextStepId)) {
                log.info("当前环节["+currStepId+"]执行完毕，流程结束");
                // 更新流程实例表
                ParamProcessInstanceBean paramInsBean = new ParamProcessInstanceBean();
                paramInsBean.setFlowId(ptaskDealBean.getFlowId());
                paramInsBean.setStatus(ProcessConst.PROCESS_INS_STATUS_ARCHIVED);
                int updInsCnt = updateDao.update("process_instance.updProcessInstanceFinish", paramInsBean);
                log.debug("process_instance.updProcessInstanceFinish FlowId=["+ptaskDealBean.getFlowId()+"] 影响行数=["+ updInsCnt +"]");
                if(updInsCnt <= 0) {
                    log.info("更新process_instance:FlowId=["+ptaskDealBean.getFlowId()+"] 影响记录数小于一条，没有造成更新");
                    throw new Exception("process_instance.updProcessInstanceFinish 更新结果返回值小于1");
                }
                
                //updateDao.commitTransaction();
                //return true;
            } else {
                // 返回结果为非结束标识，则要继续生成下一环节的待办任务
                StepBean nextStepBean = findStepBean(stepBeanLst, nextStepId);
                
                // 往process_task表中生成任务记录
                ParamProcessTaskBean paramNewTaskBean = new ParamProcessTaskBean();
                paramNewTaskBean.setFlowId(ptaskDealBean.getFlowId());
                paramNewTaskBean.setStatus(ProcessConst.PROCESS_TASK_STATUS_WAITING);
                paramNewTaskBean.setStepId(nextStepId);
                paramNewTaskBean.setStepDisplayName(nextStepBean.getDisplayName());
                
                long tkid = 0L;
                Object insTaskRsObj = updateDao.insert("process_task.insProcessTask", paramNewTaskBean);
                if(null == insTaskRsObj) {
                    log.info("process_task.insProcessTask 添加记录响应结果为 null, 插入任务表记录失败.");
                    throw new Exception("process_task.insProcessTask 添加记录响应结果为 null");
                }
                
                tkid = (Long)insTaskRsObj;
                log.debug("process_task.insProcessTask 执行后环节ID=["+ tkid +"]");
                
                // 取下一环节待办人员
                String selectRole = nextStepBean.getUserSelRole();
                String templeteName = ptaskDealBean.getTempleteName();
                
                List<?> stepUsersLst = null;
                
                // 动态指定下一环节的待办人员
                if(ProcessConst.TASK_USER_SEL_ROLE_DYNSPECIFY.equalsIgnoreCase(selectRole)) {
                    // 如果是由上一环节指定下一环节的待办人员，则需要由API调用时传入要分配任务给哪些人。
                    // 且多个人员的时候，各人员ID之间要用英文逗号分隔
                    String nextWaitUsers = ptaskDealBean.getNextStepWaitUsers();
                    stepUsersLst = StringUtil.splitStrToList(nextWaitUsers, ProcessConst.SYS_CHAR_COMMA);
                } else {
                    stepUsersLst = userSelecter.getUsersLst(selectRole, templeteName, nextStepId);
                }
                
                // 待办人员写任务关系表
                log.debug("流程["+templeteName+"]环节["+nextStepId+"]待办人员：["+stepUsersLst+"]");
                int waitUserInsRs = updateDao.batchExecuteWaitUser(stepUsersLst, tkid);
                log.debug("流程["+templeteName+"]环节["+nextStepId+"]待办人员：["+stepUsersLst+"] 批处理插入结果 =["+waitUserInsRs+"]");
            }
            
            updateDao.commitTransaction();
            return true;
        } catch (SQLException e) {
            log.error("用户["+ptaskDealBean.getDealUserId()+"]完成环节["+ptaskDealBean.getStepId()+"]异常：" + e.toString());
            e.printStackTrace();
//            try {
//                updateDao.endTransaction();
//            } catch (SQLException e1) {
//                e1.printStackTrace();
//            }
        } catch (Exception e) {
            log.error("用户["+ptaskDealBean.getDealUserId()+"]完成环节["+ptaskDealBean.getStepId()+"]异常：" + e.toString());
            e.printStackTrace();
//            try {
//                updateDao.endTransaction();
//            } catch (SQLException e1) {
//                e1.printStackTrace();
//            }
        } finally {
            try {
                updateDao.endTransaction();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }
        
        return false;
    }
    
    private StepBean findStepBean(List<StepBean> srcStepBeanLst, String stepId) {
        StepBean rs = null;
        
        if(srcStepBeanLst == null) {
            return rs;
        }
        
        for(StepBean stepBean : srcStepBeanLst) {
            if(stepId.equals(stepBean.getId())) {
                rs = stepBean;
                break;
            }
        }
        return rs;
    }
}
